// 使用某框架的 SSR API 渲染该应用
// 只在服务器运行
import { createApp } from './main.js'
import { renderToString } from '@vue/server-renderer'

export async function render(url, manifest) {
	const { app, store, router } = createApp('server')
	// const ctx = {}
	// const appHtml = await renderToString(app, ctx)
	// return { appHtml }

	// 在呈现之前，将路由器设置为所需的URL
	router.push(url)
	await router.isReady()

	// 传递SSR上下文对象，该对象将通过useSrContext（）可用
	// @vitejs/plugin-vue 将代码注入到注册的组件的setup（）中
	// 在ctx.modules上。渲染之后，ctx.modules将包含所有
	// 在此呈现调用期间实例化的组件。
	const ctx = {}
	const html = await renderToString(app, ctx)

	// Vite生成的SSR清单包含module->chunk/asset映射
	// 然后我们可以使用它来确定需要为此预加载哪些文件
	// 请求.
	const links = renderPreloadLinks(ctx.modules, manifest)

	return { html, router, store, links }
}

function renderPreloadLinks(modules, manifest) {
	let links = ''
	const seen = new Set()
	modules.forEach((id) => {
		const files = manifest[id]
		if (files) {
			files.forEach((file) => {
				if (!seen.has(file)) {
					seen.add(file)
					links += renderPreloadLink(file)
				}
			})
		}
	})
	return links
}

function renderPreloadLink(file) {
	if (file.endsWith('.js')) {
		return `<link rel="modulepreload" crossorigin href="${file}">`
	} else if (file.endsWith('.css')) {
		return `<link rel="stylesheet" href="${file}">`
	} else if (file.endsWith('.woff')) {
		return ` <link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`
	} else if (file.endsWith('.woff2')) {
		return ` <link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`
	} else if (file.endsWith('.gif')) {
		return ` <link rel="preload" href="${file}" as="image" type="image/gif" crossorigin>`
	} else if (file.endsWith('.jpg')) {
		return ` <link rel="preload" href="${file}" as="image" type="image/jpeg" crossorigin>`
	} else if (file.endsWith('.jpeg')) {
		return ` <link rel="preload" href="${file}" as="image" type="image/jpeg" crossorigin>`
	} else if (file.endsWith('.png')) {
		return ` <link rel="preload" href="${file}" as="image" type="image/png" crossorigin>`
	} else {
		// TODO
		return ''
	}
}
